package net.butfly.bus.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import net.butfly.bus.exception.BusRuntimeException;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.io.IOUtils;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;

public class ObjectUtils {
	private final static String DEFAULT_KEY = "type";
	private final static String DEFAULT_TYPE = "String";
	private final static String INTEGER_TYPE = "Integer";
	private final static String BIGDECIMAL_TYPE = "BigDecimal";
	private final static String BOOLEAN_TYPE = "boolean";
	private final static String DATE_TYPE = "Date";
	private final static String MAP_TYPE = "java.util.Map";
	private final static String LIST_TYPE = "java.util.List";

	public Object parse(String filename) throws IllegalAccessException, InvocationTargetException,
			InstantiationException, ClassNotFoundException, IOException, DocumentException {
		InputStream is = new FileInputStream(new File(filename));
		String xmlStr = IOUtils.toString(is);
		Element element = getRootElement(xmlStr);
		String type = element.attributeValue(DEFAULT_KEY);
		Object object = null;

		String value = element.getTextTrim();

		if (type.startsWith(LIST_TYPE)) {
			object = new ArrayList<Object>();
		} else if (type.startsWith(MAP_TYPE)) {
			object = new HashMap<String, Object>();
		} else if (INTEGER_TYPE.equalsIgnoreCase(type)) {
			return new Integer(value);
		} else if (BIGDECIMAL_TYPE.equalsIgnoreCase(type)) {
			return new BigDecimal(value);
		} else if (BOOLEAN_TYPE.equalsIgnoreCase(type)) {
			return new Boolean(value);
		} else if (DATE_TYPE.equalsIgnoreCase(type)) {
			return parseDate(value);
		} else if (!value.equals("")) {
			return new String(value);
		} else {
			object = Class.forName(type).newInstance();
		}
		Object result = getElementList(element, object, type);
		// Object object = System.out.println("result:"+result.toString());
		return result;

		// BeanUtils.setProperty(bean, name, value);
	}

	private Element getRootElement(String srcXml) throws DocumentException {
		Document srcdoc = DocumentHelper.parseText(srcXml);
		Element elem = srcdoc.getRootElement();
		return elem;
	}

	@SuppressWarnings("unchecked")
	private Object getElementList(Element element, Object object, String type) throws IllegalAccessException,
			InvocationTargetException, InstantiationException, ClassNotFoundException {
		List<?> elements = element.elements();
		for (Iterator<?> it = elements.iterator(); it.hasNext();) {
			Element elem = (Element) it.next();
			String elemType = elem.attributeValue(DEFAULT_KEY);
			if (null == elemType) {
				elemType = DEFAULT_TYPE;
			}
			if (DEFAULT_TYPE.equalsIgnoreCase(elemType) || INTEGER_TYPE.equalsIgnoreCase(elemType)
					|| BIGDECIMAL_TYPE.equalsIgnoreCase(elemType) || BOOLEAN_TYPE.equalsIgnoreCase(elemType)
					|| DATE_TYPE.equalsIgnoreCase(elemType)) {
				if (DATE_TYPE.equals(elemType)) {
					BeanUtils.setProperty(object, elem.getName(), parseDate(elem.getTextTrim()));
				} else {
					BeanUtils.setProperty(object, elem.getName(), elem.getTextTrim());
				}
			} else {
				Object elemObject = null;
				if (elemType.startsWith(LIST_TYPE)) {
					elemObject = new ArrayList<Object>();
				} else if (elemType.startsWith(MAP_TYPE)) {
					elemObject = new HashMap<Object, Object>();
				} else {
					elemObject = Class.forName(elemType).newInstance();
				}

				if (type.startsWith(LIST_TYPE)) {
					List<Object> l = (List<Object>) object;
					l.add(getElementList(elem, elemObject, elemType));
				} else if (type.startsWith(MAP_TYPE)) {
					Map<String, Object> map = (Map<String, Object>) object;
					map.put(elem.getName(), getElementList(elem, elemObject, elemType));
				} else {
					BeanUtils.setProperty(object, elem.getName(), getElementList(elem, elemObject, elemType));
				}
			}
		}
		return object;
	}

	private Date parseDate(String str) {
		try {
			str = str.replace(" ", "-");
			str = str.replace(":", "-");
			String[] tempStr = str.split("-");
			int y = Integer.parseInt(tempStr[0]) - 1900;
			int m = Integer.parseInt(tempStr[1]) - 1;
			int d = Integer.parseInt(tempStr[2]);
			int hour = Integer.parseInt(tempStr[3]);
			int min = Integer.parseInt(tempStr[4]);
			int sec = Integer.parseInt(tempStr[5]);
			return new Date(y, m, d, hour, min, sec);
		} catch (Exception e) {
			throw new BusRuntimeException("日期格式出错");
		}
	}

	public static void main(String[] args) throws Exception {
		String userDir = System.getProperty("user.dir");
		String filePath = "/src/test/com/cmb/ewin/test/utils/xml/";

		ObjectUtils of = new ObjectUtils();
		// System.out.println(userDir);
		String filename = userDir + filePath + "SimpleObject4.xml";
		Object object = of.parse(filename);
		System.out.println("filename: " + filename);
		System.out.println("result:   " + object.toString());
		System.out.println("------------------------------------------");

		/*
		 * // System.out.println(userDir); filename = userDir + filePath +
		 * "SimpleObject2.xml"; object = of.parse(filename);
		 * System.out.println("filename: " + filename);
		 * System.out.println("result: " + object.toString());
		 * System.out.println("------------------------------------------"); //
		 * System.out.println(userDir); filename = userDir + filePath +
		 * "SimpleObject3.xml"; object = of.parse(filename);
		 * System.out.println("filename: " + filename);
		 * System.out.println("result: " + object.toString());
		 * System.out.println("------------------------------------------"); //
		 * System.out.println(userDir); filename = userDir + filePath +
		 * "SimpleObject1.xml"; object = of.parse(filename);
		 * System.out.println("filename: " + filename);
		 * System.out.println("result: " + object.toString());
		 * System.out.println("------------------------------------------");
		 */

	}
}
